package config

import (
	"os"
	"path/filepath"
	"strings"
)

// EnvModeName indicates environment name for system environment mode.
// Different system might have unique mode name.
// This is used in terminal to set the env before running.
const EnvModeName = "OP_ENV_MODE"

const (
	DevMode   = "dev"
	LocalMode = "local"
	ProdMode  = "prod"
	TestMode  = "test"
)

// The public member is shared within entire application.
var SysEnvMode EnvMode

type EnvMode interface {
	GetCurrentMode() string
	SetCurrentMode(mode string)
	IsProdMode() bool
	IsDevMode() bool
	IsTestMode() bool
	String() string
}

func NewEnvMode() EnvMode {
	s := &envMode{}
	s.InitFromEnv()

	return s
}

// InitFromEnv initializes the environment mode from the system environment variable.
func (s *envMode) InitFromEnv() {
	mode := os.Getenv(EnvModeName)
	s.SetCurrentMode(mode)
}

func (s *envMode) GetCurrentMode() string {
	return s.mode
}

func (s *envMode) SetCurrentMode(mode string) {
	mode = strings.ToLower(strings.TrimSpace(mode))

	if strings.TrimSpace(mode) == "" {
		mode = DevMode
	}

	s.mode = mode
}

// IsDevMode returns true if the current mode is development.
func (s *envMode) IsDevMode() bool {
	return s.mode == DevMode
}

// IsDevMode returns true if the current mode is local container.
func (s *envMode) IsLocalMode() bool {
	return s.mode == LocalMode
}

// IsProdMode returns true if the current mode is production.
func (s *envMode) IsProdMode() bool {
	return s.mode == ProdMode
}

// IsTestMode returns true if the current mode is testing.
func (s *envMode) IsTestMode() bool {
	return s.mode == TestMode
}

// String returns the current mode as a string.
func (s *envMode) String() string {
	return s.mode
}

// Gets the directory name that startedd the current process.
func GetExecutableDirectory() (string, error) {
	// Gets the path name for the executable that started the current process.
	pathExecutable, err := os.Executable()

	if err != nil {
		return "", err
	}

	return filepath.Dir(pathExecutable), nil
}

type envMode struct {
	mode string
}
